我們已經知道全域執行環境會替我們產生全域物件(Global Object)與特殊變數 this,在執行環境裡也會產生外部環境,
執行環境分成兩個階段,我們先來看第1階段,第1階段是創造階段,
透過範例來看:
var a = 'Hello World!';
function b() {
console.log('Called b!');
}
b();
console.log(a);
透過 Chrome 的 Console 來看結果如下:
我們再把程式碼改寫如下:
b();
console.log(a);
function b() {
console.log('Called b!');
}
會看到 Console 中的結果如下:
因為我們沒有宣告變數,
當執行環境在創造階段時,變數 a 沒有被設定進記憶體空間中,
所以會出現錯誤,
但如果們們改變一下程式碼的順序,將程式碼調整如下:
b();
console.log(a);
var a = 'Hello World!';
function b() {
console.log('Called b!');
}
現在在 Console 中變數 a 輸出的值為 undefined:
在其他程式語言中,這樣可能會報錯,但 JavaScript 不會,
因為電腦無法直接看懂 JavaScript ,
需要透過語法解析器將 JavaScript 轉換成電腦看的懂的東西,
電腦實際在執行轉換後的指令時執行環境被創造,
在執行環境的創造階段時變數與函數會被設定進記憶體空間,
這個現象稱作 hoisting,
接著是執行階段,
可以將剛才的程式碼看成這樣:
var a;
console.log(a); // undefined
a = 'Hello World!';
執行環境在創造階段時,不知道變數的值為何,
會將變數的預設值設為 undefined,
只有在執行環境進入執行階段時(變數被等號這種賦值符號賦值時)才會知道變數的值:
var a;
a = 'Hello World!';
console.log(a); // 'Hello World!'
接著來了解 JavaScript 和 undefined
之間的關係,
我們再回顧創造執行環境的第1階段,
在執行環境被創造的創造階段,會在全域執行環境幫我們產生全域物件、特殊變數 this 與外部環境(如果有外部環境 this 會與外部環境連結),還會在創造階段替我們將變數與函數設置到記憶體空間(hoisting),
圖片來源:JavaScript 全攻略:克服 JS 的奇怪部分課程第 2 節講座 11 影片截圖
變數在創造階段時會被設定一個初始值 undefined
,
我們來看個例子:
var a;
console.log(a);
我們到 Chrome 的 Console 中看:
會看到 undefined
,
但如果我們不用 var 宣告變數,
直接把 a
console.log
出來:
console.log(a);
會看到結果如下:
你可能會好奇, undefined
跟 is not defined
的差異,
讓我們再來看個例子:
var a;
console.log(a);
if (a === undefined) {
console.log('a is undefined!');
}
else {
console.log('a is defined!');
}
在執行環境的創造階段就在記憶體空間中設定變數 a
的值為 undefined
,
可以看到在 if 判斷中 我們用3個等號(之後會解釋)來比較 a
與 undefined
,
如果 a 等於 undefined
(undefined
不是字串,沒有加單(雙)引號,是 JavaScript 中特殊的值),我們在 Chrome 的 Console 中看到結果如下:
如果我們再將 var a
拿掉:
console.log(a);
if (a === undefined) {
console.log('a is undefined!');
}
else {
console.log('a is defined!');
}
在 Chrome 的 Console 結果如下:
這是因為在執行環境的創造階段,變數 a
尚未被設定到記憶體中,
所以在進入執行階段時,JavaScript 的執行環境會說「嘿,我在記憶體中找不到 a
這個值」,所以會顯示參照不到這個值的錯誤,
undefined
不代表沒有被設值,會佔據記憶體空間,是 JavaScript 中特殊的關鍵字,一個特殊的值,表示這是 JavaScript 設定的初始值,
永遠不要手動將變數設值為 undefined
,
我們再來看這個例子:
var a = 'Hello World!';
console.log(a);
a = undefined;
if (a === undefined) {
console.log('a is undefined!');
}
else {
console.log('a is defined!');
}
在 Chrome 的 Console 中會看到結果如下:
可以看到在 JavaScript 中這樣是完全有效的,
但不建議這樣做,
因為這樣就分辨不出 undefined
是 JavaScript 幫我們設定的初始值或是我們自己設定的了,
這在除錯時會替自己找麻煩,最好讓 undefined
表示我從未設定過這個值。